package com.sxj.corejava.code08_常用类.String类;

/**
 * @author 石小俊
 * @date 2025年01月11日
 */
public class Test09_常量池 {

    public static void main(String[] args) {
        // 在堆中开辟一块空间,用于存储admin
        String s1 = new String("admin");
        // 在堆中再次开辟空间,用于存储alice,s1的引用从指向admin变为指向alice
        s1 = new String("alice");
        // 在堆中开辟一块空间用于存储admin,s2指向该空间
        // 在代码中,只要出现new Xxx,均表示在堆中开辟一块空间
        String s2 = new String("admin");

        // 常量池
        // 在常量池中开辟一块空间,用于存储admin
        String s3 = "admin";
        // 在常量池中开辟一块空间,用于存储alice,此时s3指向该空间
        s3 = "alice";
        // 由于常量池中已经有空间的值为admin了,因此并没有开辟新的空间
        // 而是将s4直接指向了原有的空间
        String s4 = "admin";
        String s5 = "admin";
        // 由于s4与s4处于常量池中的同一块空间,其内存地址相同,值相同,返回true
        System.out.println(s4 == s5);   // true

        String s6 = new String("admin");
        // 由于s2与s6在堆中并不是同一块空间,其内存地址不同,因此返回false
        System.out.println(s2 == s6);   // false
        // s4处于常量池中,s6处于堆中,内存地址一定不同,false
        System.out.println(s4 == s6);

        String s7 = "a";
        String s8 = "aa";
        String s9 = "aaa";
        String s10 = "a" + "aa";
        // 由于s10最终结果为aaa,且处于常量池中,因此与s9处于同一块空间
        System.out.println(s9 == s10);  // true
        String s11 = s7 + s8;
        // 此时的s11并不是字符常量,没有存储到常量池中,而是存储在堆中
        // 在进行运算时,如果其运算过程中涉及的所有数据均在编译时就可以确定,则表示存储在常量池中
        // 如果在运行时才能确定,则存储在堆中
        // 因此,此时的s11存储在堆中,而s9存储在常量池中,其内存地址一定不同
        System.out.println(s9 == s11);  // false

        String s12 = s7 + "aa";
        System.out.println(s9 == s12);  // false
    }
}
